home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************
- Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
- Amsterdam, The Netherlands.
-
- All Rights Reserved
-
- Permission to use, copy, modify, and distribute this software and its
- documentation for any purpose and without fee is hereby granted,
- provided that the above copyright notice appear in all copies and that
- both that copyright notice and this permission notice appear in
- supporting documentation, and that the names of Stichting Mathematisch
- Centrum or CWI not be used in advertising or publicity pertaining to
- distribution of the software without specific, written prior permission.
-
- STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
- THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
- FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
- FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
- OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
- ******************************************************************/
-
- #include "Python.h"
- #include "import.h"
- #include "ppm.h"
-
- /* The image formats we support */
- static PyObject *format_rgb, *format_rgb_b2t, *format_choices;
- extern PyObject *getimgformat(); /* Get foirmat by name */
-
- /*
- ** Since PBMPLUS error handling is abysmal (print message, exit),
- ** there is a modified version that has (slightly) better error
- ** handling. Contact jack@cwi.nl if you want it. Define PBMNEWERROR
- ** if you have the modified pbmplus.
- **
- ** If you don't have it the first pbm error will abort you python
- ** program.
- */
- #define PBMNEWERROR
-
- #ifndef PBMNEWERROR
- #define PPM_END
- #define PPM_START if (0) {
- #define PPM_ENDSTART }
-
- #else
-
- #include <setjmp.h>
- jmp_buf ppmerrenv;
- char ppmerrstr[1000];
-
- #define PPM_END pm_setmsghandler(0); pm_setexithandler(0);
- #define PPM_START if ( setjmp(ppmerrenv) != 0 ) { \
- PyErr_SetString(errobject, ppmerrstr); \
- *ppmerrstr = '\0'; \
- PPM_END
- #define PPM_ENDSTART return 0; \
- } \
- pm_setmsghandler(my_pmerr); \
- pm_setexithandler(my_pmexit);
-
-
- static void
- my_pmerr(str)
- char *str;
- {
- strncpy(ppmerrstr, str, 999);
- }
-
- static void
- my_pmexit()
- {
- longjmp(ppmerrenv, 1);
- }
-
- #endif /* PBMNEWERROR */
-
- /* Ppm objects */
-
- typedef struct {
- PyObject_HEAD
- PyObject *dict; /* Attributes dictionary */
- int is_reader; /* TRUE if this is a reader */
- char *filename; /* filename of the image file */
- FILE *filep;
- pixval maxval;
- int format;
- } ppmobject;
-
- static PyObject *errobject;
-
- staticforward PyTypeObject Ppmtype;
-
- #define is_ppmobject(v) ((v)->ob_type == &Ppmtype)
-
- static char doc_ppm[] = "This object reads/writes PPM files\n"
- "The 'width', 'height' and 'format' attributes describe the picture\n"
- "For writers, setting 'forceplain' creates an ASCII PPM file.";
-
- /* Routine to easily obtain C data from the dict python data */
- int
- ppmselfattr(self, name, fmt, ptr, wanterr)
- ppmobject *self;
- char *name;
- char *fmt;
- void *ptr;
- int wanterr;
- {
- PyObject *obj;
- char errbuf[100];
-
- obj = PyDict_GetItemString(self->dict, name);
- if ( obj == NULL ) {
- if ( wanterr ) {
- sprintf(errbuf, "Required attribute '%s' not set", name);
- PyErr_SetString(errobject, errbuf);
- return 0;
- } else {
- PyErr_Clear();
- return 0;
- }
- }
- if ( !PyArg_Parse(obj, fmt, ptr) ) {
- if ( !wanterr )
- PyErr_Clear();
- return 0;
- }
- return 1;
- }
-
- /* Routine to easily insert integer into dictionary */
- ppmsetintattr(self, name, value)
- ppmobject *self;
- char *name;
- int value;
- {
- PyObject *obj;
- int rv;
-
- obj = PyInt_FromLong(value);
- rv = PyDict_SetItemString(self->dict, name, obj);
- Py_DECREF(obj);
- return rv;
- }
-
- static ppmobject *
- newppmobject()
- {
- ppmobject *xp;
- xp = PyObject_NEW(ppmobject, &Ppmtype);
- if (xp == NULL)
- return NULL;
- xp->dict = PyDict_New();
- xp->filename = NULL;
- xp->filep = NULL;
- return xp;
- }
-
- static int
- initppmreader(self, name)
- ppmobject *self;
- char *name;
- {
- char *name_copy;
- int cols, rows;
- pixval old_pbmmaxval;
-
- if( (name_copy=malloc(strlen(name)+1)) == NULL ) {
- PyErr_NoMemory();
- return 0;
- }
- strcpy(name_copy, name);
- self->filename = name_copy;
- self->is_reader = 1;
-
- if ((self->filep = fopen(self->filename, "rb")) == NULL ) {
- PyErr_SetFromErrno(PyExc_IOError);
- return 0;
- }
- PPM_START
- fclose(self->filep);
- self->filep = 0;
- return 0;
- PPM_ENDSTART
- old_pbmmaxval = ppm_pbmmaxval;
- ppm_pbmmaxval = 0xff; /* XXXX Correct for rgb/rgb_b2t formats */
- ppm_readppminit(self->filep, &cols, &rows, &self->maxval,
- &self->format);
- ppm_pbmmaxval = old_pbmmaxval;
- PPM_END
-
- ppmsetintattr(self, "width", cols);
- ppmsetintattr(self, "height", rows);
- PyDict_SetItemString(self->dict, "format", format_rgb);
- PyDict_SetItemString(self->dict, "format_choices", format_choices);
- if ( PyErr_Occurred() )
- return 0;
- return 1;
- }
-
- static int
- initppmwriter(self, name)
- ppmobject *self;
- char *name;
- {
- char *name_copy;
-
- if( (name_copy=malloc(strlen(name)+1)) == NULL ) {
- PyErr_NoMemory();
- return 0;
- }
- strcpy(name_copy, name);
- self->filename = name_copy;
- self->filep = NULL;
- self->is_reader = 0;
- PyDict_SetItemString(self->dict, "format", format_rgb);
- PyDict_SetItemString(self->dict, "format_choices", format_choices);
- if( PyErr_Occurred())
- return 0;
- return 1;
- }
-
- /* Ppm methods */
-
- static void
- ppm_dealloc(xp)
- ppmobject *xp;
- {
- Py_XDECREF(xp->dict);
- if( xp->filename )
- free(xp->filename);
- if( xp->filep )
- fclose(xp->filep);
- PyMem_DEL(xp);
- }
-
- static char doc_read[] = "Read the actual data, returns a string";
-
- static PyObject *
- ppm_read(self, args)
- ppmobject *self;
- PyObject *args;
- {
- int i, w, h, toptobottom, rowlen;
- PyObject *rv;
- long *datap;
- pixel *pixelrow;
- pixel ppmpixel;
- long rgbpixel;
- PyObject *fmt;
-
- if (!PyArg_ParseTuple(args,""))
- return NULL;
- if (!self->is_reader) {
- PyErr_SetString(errobject, "Cannot read() from writer object");
- return NULL;
- }
- /* XXXX Read data and return it */
- /* XXXX Get args from self->dict and write the data */
- if ( !ppmselfattr(self, "width", "i", &w, 1) ||
- !ppmselfattr(self, "height", "i", &h, 1) ||
- !ppmselfattr(self, "format", "O", &fmt, 1) )
- return NULL;
- if ( fmt == format_rgb )
- toptobottom = 1;
- else if ( fmt == format_rgb_b2t )
- toptobottom = 0;
- else {
- PyErr_SetString(errobject, "Unsupported image format");
- return NULL;
- }
- pixelrow = 0;
- rv = 0;
- PPM_START
- if ( pixelrow )
- pbm_freerow(pixelrow);
- if ( rv )
- Py_DECREF(rv);
- return NULL;
- PPM_ENDSTART
-
- pixelrow=ppm_allocrow(w);
- if ( (rv=PyString_FromStringAndSize(0, w*h*4)) == NULL ) {
- pbm_freerow(pixelrow);
- return NULL;
- }
- datap = (long *)PyString_AsString(rv);
-
- if ( toptobottom ) {
- rowlen = w;
- } else {
- rowlen = -w;
- datap = datap + w*(h-1);
- }
-
- while( h > 0 ) {
- ppm_readppmrow(self->filep, pixelrow, w, self->maxval,
- self->format);
- for(i=0; i<w; i++) {
- ppmpixel = pixelrow[i];
- rgbpixel = PPM_GETR(ppmpixel);
- rgbpixel |= (PPM_GETG(ppmpixel)) << 8;
- rgbpixel |= (PPM_GETB(ppmpixel)) << 16;
- datap[i] = rgbpixel;
- }
- datap += rowlen;
- h -= 1;
- }
- PPM_END
- pbm_freerow(pixelrow);
- return rv;
- }
-
- static char doc_write[] = "Write (string) data to the PPM file";
-
- static PyObject *
- ppm_write(self, args)
- ppmobject *self;
- PyObject *args;
- {
- long *data;
- int datalen;
- int i, w, h, rowlen;
- PyObject *fmt;
- int toptobottom;
- pixel *pixelrow;
- pixel ppmpixel;
- long rgbpixel;
- int forceplain;
- FILE *filep;
-
- if (!PyArg_ParseTuple(args, "s#", &data, &datalen))
- return NULL;
- if (self->is_reader) {
- PyErr_SetString(errobject, "Cannot write() to reader object");
- return NULL;
- }
- /* XXXX Get args from self->dict and write the data */
- if ( !ppmselfattr(self, "width", "i", &w, 1) ||
- !ppmselfattr(self, "height", "i", &h, 1) ||
- !ppmselfattr(self, "format", "O", &fmt, 1) )
- return NULL;
- if( w*h*4 != datalen ) {
- PyErr_SetString(errobject, "Incorrect datasize");
- return NULL;
- }
- forceplain = 0;
- ppmselfattr(self, "forceplain", "i", &forceplain, 0);
-
- if ( fmt == format_rgb ) {
- toptobottom = 1;
- rowlen = w;
- } else if ( fmt == format_rgb_b2t ) {
- toptobottom = 0;
- rowlen = -w;
- data = data + w*(h-1);
- } else {
- PyErr_SetString(errobject, "Unsupported image format");
- return NULL;
- }
- if ((filep = fopen(self->filename, forceplain?"w":"wb")) == NULL) {
- PyErr_SetFromErrno(PyExc_IOError);
- return 0;
- }
- #ifdef macintosh
- setfiletype(self->filename, '????', 'PPGM');
- #endif
- pixelrow = 0;
- PPM_START
- if ( pixelrow )
- pbm_freerow(pixelrow);
- fclose(filep);
- return NULL;
- PPM_ENDSTART
-
- pixelrow=ppm_allocrow(w);
-
- ppm_writeppminit(filep, w, h, 0xff, forceplain);
- while( h > 0 ) {
- for(i=0; i<w; i++) {
- rgbpixel = data[i];
- PPM_ASSIGN(ppmpixel, rgbpixel&0xff, (rgbpixel>>8) & 0xff,
- (rgbpixel>>16)&0xff);
- pixelrow[i] = ppmpixel;
- }
- ppm_writeppmrow(filep, pixelrow, w, 0xff, forceplain);
- data += rowlen;
- h -= 1;
- }
- PPM_END
- pbm_freerow(pixelrow);
- if (fclose(filep) != 0) {
- PyErr_SetFromErrno(PyExc_IOError);
- return NULL;
- }
- Py_INCREF(Py_None);
- return Py_None;
- }
-
- static struct PyMethodDef ppm_methods[] = {
- {"read", (PyCFunction)ppm_read, 1, doc_read},
- {"write", (PyCFunction)ppm_write, 1, doc_write},
- {NULL, NULL} /* sentinel */
- };
-
- static PyObject *
- ppm_getattr(xp, name)
- ppmobject *xp;
- char *name;
- {
- PyObject *v;
-
- if (xp->dict != NULL) {
- if ( strcmp(name, "__dict__") == 0 ) {
- Py_INCREF(xp->dict);
- return xp->dict;
- }
- if ( strcmp(name, "__doc__") == 0 ) {
- return PyString_FromString(doc_ppm);
- }
- v = PyDict_GetItemString(xp->dict, name);
- if (v != NULL) {
- Py_INCREF(v);
- return v;
- }
- }
- return Py_FindMethod(ppm_methods, (PyObject *)xp, name);
- }
-
- static int
- ppm_setattr(xp, name, v)
- ppmobject *xp;
- char *name;
- PyObject *v;
- {
- if (xp->dict == NULL) {
- xp->dict = PyDict_New();
- if (xp->dict == NULL)
- return -1;
- }
- if (v == NULL) {
- int rv = PyDict_DelItemString(xp->dict, name);
- if (rv < 0)
- PyErr_SetString(PyExc_AttributeError,
- "delete non-existing imgppm attribute");
- return rv;
- }
- else
- return PyDict_SetItemString(xp->dict, name, v);
- }
-
- static PyTypeObject Ppmtype = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /*ob_size*/
- "imgppm", /*tp_name*/
- sizeof(ppmobject), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- /* methods */
- (destructor)ppm_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- (getattrfunc)ppm_getattr, /*tp_getattr*/
- (setattrfunc)ppm_setattr, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash*/
- };
-
- static char doc_newreader[] =
- "Return an object that reads the PPM/PGM/PBM file passed as argument";
-
- static PyObject *
- ppm_newreader(self, args)
- PyObject *self;
- PyObject *args;
- {
- char *filename;
- ppmobject *obj;
-
- if (!PyArg_ParseTuple(args, "s", &filename))
- return NULL;
- if ((obj = newppmobject()) == NULL)
- return NULL;
- if ( !initppmreader(obj, filename) ) {
- ppm_dealloc(obj);
- return NULL;
- }
- return (PyObject *)obj;
- }
-
- static char doc_newwriter[] =
- "Return an object that writes the PPM file passed as argument";
-
- static PyObject *
- ppm_newwriter(self, args)
- PyObject *self;
- PyObject *args;
- {
- char *filename;
- ppmobject *obj;
-
- if (!PyArg_ParseTuple(args, "s", &filename))
- return NULL;
- if ((obj = newppmobject()) == NULL)
- return NULL;
- if ( !initppmwriter(obj, filename) ) {
- ppm_dealloc(obj);
- return NULL;
- }
- return (PyObject *)obj;
- }
-
-
- /* List of functions defined in the module */
-
- static struct PyMethodDef ppm_module_methods[] = {
- {"reader", ppm_newreader, 1, doc_newreader},
- {"writer", ppm_newwriter, 1, doc_newwriter},
- {NULL, NULL} /* sentinel */
- };
-
-
- /* Initialization function for the module (*must* be called initimgppm) */
- static char doc_imgppm[] =
- "Module that reads images from PPM/PGM/PBM files and writes to PPM files.";
-
- void
- initimgppm()
- {
- PyObject *m, *d, *x, *formatmodule, *formatdict;
-
- /* Create the module and add the functions */
- m = Py_InitModule("imgppm", ppm_module_methods);
-
- /* Add some symbolic constants to the module */
- d = PyModule_GetDict(m);
- errobject = PyString_FromString("imgppm.error");
- PyDict_SetItemString(d, "error", errobject);
- x = PyString_FromString(doc_imgppm);
- PyDict_SetItemString(d, "__doc__", x);
-
- /* Get supported formats */
- if ((formatmodule = PyImport_ImportModule("imgformat")) == NULL)
- Py_FatalError("imgppm depends on imgformat");
- if ((formatdict = PyModule_GetDict(formatmodule)) == NULL)
- Py_FatalError("imgformat has no dict");
-
- format_rgb = PyDict_GetItemString(formatdict,"rgb");
- format_rgb_b2t = PyDict_GetItemString(formatdict,"rgb_b2t");
- format_choices = Py_BuildValue("(OO)", format_rgb, format_rgb_b2t);
-
- /* Initialize pbmplus */
- {
- int ppm_argc;
- static char *ppm_arglist[] = { "pbmplus", 0};
- char **ppm_argv;
-
- ppm_argc = 1;
- ppm_argv = ppm_arglist;
- PPM_START /* { */
- Py_FatalError("pbmplus initialization error");
- } /* PPM_ENDSTART won't work here, it has return NULL */
- ppm_init(&ppm_argc, ppm_argv);
- PPM_END
- }
-
- /* Check for errors */
- if (PyErr_Occurred())
- Py_FatalError("can't initialize module imgppm");
- }
-